home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’97 / TempoHelper / source code / TempoHelper.c < prev    next >
C/C++ Source or Header  |  1997-06-28  |  10KB  |  405 lines

  1. /* File: ASM.c */
  2.  
  3. #include <Errors.h>
  4. #include <SetUpA4.h>
  5. #include <A4Stuff.h>
  6. #include <Icons.h>
  7. #include "iconsextra.h"
  8.  
  9. #define     ICON_SUCCESS    1025
  10. #define        ICON_FAILURE    1026
  11. #define        MyMenuID        -16509
  12. #define        MyIconFamilyID    1024
  13.  
  14.  
  15. // Special Undocumented Routines for System Mode
  16. pascal OSErr TurnSystemModeOn(void)  = {0x3F3C, 0x0040, 0xA88F}; 
  17. pascal OSErr TurnSystemModeOff(void) = {0x3F3C, 0x0041, 0xA88F}; 
  18.  
  19.  
  20. long        gSystemMenuAddress;    
  21. long        gDrawMenuBarAddress;
  22. long        gMenuSelectAddress;
  23. long        gMenuKeyAddress;
  24. long        gSetItemAddress;
  25. long        gInsertMenuAddress;
  26. FSSpec        gInitFSSpec;                /* An FSSpec to this file (so we can get at it later) */
  27. MenuHandle    gMenuHandle;                /* Our menu, as skanky as it is */
  28. Handle        gIconSuite;                    /* The icon suite for the title of our menu */
  29. MenuHandle    gHelpMenu;
  30. Boolean        gMenuInstalled;                /* Have we set up our menu yet? */
  31.  
  32.  
  33. // prototypes
  34. typedef    pascal    void    (*DrawMenuBarProcPtr) ();
  35. #define callDrawMenuBar(userRoutine)        \
  36.             (*(DrawMenuBarProcPtr)(userRoutine))()
  37.  
  38. typedef    pascal    long    (*MenuSelectProcPtr) (Point startPt);
  39. #define callMenuSelect(userRoutine, startPt)        \
  40.             (*(MenuSelectProcPtr)(userRoutine))((startPt))
  41.  
  42. typedef    pascal    long    (*MenuKeyProcPtr) (short ch);
  43. #define callMenuKey(userRoutine, ch)        \
  44.             (*(MenuKeyProcPtr)(userRoutine))((ch))
  45.  
  46. typedef    pascal    void    (*SystemMenuProcPtr) (long menuResult);
  47. #define callSystemMenu(userRoutine, menuResult)        \
  48.             (*(SystemMenuProcPtr)(userRoutine))((menuResult))
  49.  
  50. typedef    pascal    void    (*SetMenuItemProcPtr) (MenuRef menuH, short item, ConstStr255Param itemString);
  51. #define callSetMenuItemText(userRoutine, menuH, item, itemString)        \
  52.             (*(SetMenuItemProcPtr)(userRoutine))((menuH), (item), (itemString))
  53.  
  54. typedef    pascal    void    (*InsertMenuProcPtr) (MenuRef menuH, short beforeID);
  55. #define callInsertMenu(userRoutine, menuH, beforeID)        \
  56.             (*(InsertMenuProcPtr)(userRoutine))((menuH), (beforeID))
  57.  
  58.  
  59.  
  60. extern pascal void ShowIcon7( short iconId, Boolean advance );
  61. static OSErr GetFileFromRefNum (short fRefNum, short *volID, long *dirID, StringPtr name);
  62. pascal    void         MyDrawMenuBar(void);
  63. pascal    void         MySystemMenu(long MenuCode);
  64. pascal     long         MyMenuSelect(Point startPt);
  65. pascal     long         MyMenuKey(short theChar);
  66. pascal     long         MyMenuKey(short theChar);
  67. pascal    void        MySetMenuItemText(MenuRef theMenu, short item, ConstStr255Param itemString);
  68. pascal    void        MyInsertMenu(MenuRef theMenu, short beforeID);
  69.  
  70. pascal void main()
  71. {
  72.     Handle     initHandle;
  73.     THz        currZone;
  74.     Handle    oneIcon;
  75.     short    iconNum;
  76.     OSErr    err;
  77.  
  78.     EnterCodeResource();
  79.     PrepareCallback();        // setup a4 for later usage!
  80.  
  81.     /* Locate this resource in memory and detach it */
  82.     initHandle = Get1Resource('INIT', 1024);
  83.     HNoPurge(initHandle);
  84.     DetachResource(initHandle);
  85.     
  86.  
  87.     err = GetFileFromRefNum(CurResFile(), &gInitFSSpec.vRefNum, &gInitFSSpec.parID, gInitFSSpec.name);
  88.     if (err) { /*Debugger();*/ goto done; }    /* <<< If we display an icon, this should indicate a failure */
  89.  
  90.     /*
  91.         Install the trap patches
  92.     */
  93.     gDrawMenuBarAddress = (long)NGetTrapAddress(_DrawMenuBar, ToolTrap);
  94.     NSetTrapAddress((UniversalProcPtr)MyDrawMenuBar, _DrawMenuBar, ToolTrap);
  95.  
  96.     gSystemMenuAddress = (long)NGetTrapAddress(_SystemMenu, ToolTrap);
  97.     NSetTrapAddress((UniversalProcPtr)MySystemMenu, _SystemMenu, ToolTrap);
  98.  
  99.     gMenuSelectAddress = (long)NGetTrapAddress(_MenuSelect, ToolTrap);
  100.     NSetTrapAddress((UniversalProcPtr)MyMenuSelect, _MenuSelect, ToolTrap);
  101.  
  102.     gMenuKeyAddress = (long)NGetTrapAddress(_MenuKey, ToolTrap);
  103.     NSetTrapAddress((UniversalProcPtr)MyMenuKey, _MenuKey, ToolTrap);
  104.  
  105.     gSetItemAddress = (long)NGetTrapAddress(_SetItem, ToolTrap);
  106.     NSetTrapAddress((UniversalProcPtr)MySetMenuItemText, _SetItem, ToolTrap);
  107.  
  108.     gInsertMenuAddress = (long)NGetTrapAddress(_InsertMenu, ToolTrap);
  109.     NSetTrapAddress((UniversalProcPtr)MyInsertMenu, _InsertMenu, ToolTrap);
  110.  
  111.  
  112.     currZone = GetZone();
  113.     SetZone(SystemZone());
  114.  
  115.     gMenuHandle = NewMenu(MyMenuID, "\pxyzzy");
  116.         
  117.     // load the icon suite and then detach all entries
  118.     if (GetIconSuite(&gIconSuite, MyIconFamilyID, svAllAvailableData) == noErr) {
  119.         HLock(gIconSuite);
  120.         for (iconNum = largeIcon1; iconNum <= miniIcon8; iconNum++) {
  121.             oneIcon = (**((IconSuiteHandle)gIconSuite)).table[iconNum];
  122.             if (oneIcon) DetachResource(oneIcon);
  123.         }
  124.         HUnlock(gIconSuite);
  125.         BlockMoveData(&gIconSuite, &(**gMenuHandle).menuData[2], 4);
  126.         (**gMenuHandle).menuData[1] = ~(**gMenuHandle).menuData[1] & 1;
  127.     }
  128.  
  129.     
  130.     SetZone(currZone);
  131.  
  132.     gMenuInstalled = FALSE;
  133.     
  134. done:
  135.  
  136.     ShowIcon7( (!err ? ICON_SUCCESS : ICON_FAILURE), TRUE );
  137.     
  138.     ExitCodeResource();
  139. }
  140.  
  141. static asm    void    saveregisters (void)
  142. {
  143.     move.l    (sp)+,a0            // the return address in a0
  144.     movem.l    d0-d2/a1,-(sp)                // which is not saved
  145.     jmp        (a0)
  146. }
  147.  
  148. static asm    void    restoreregisters (void)
  149. {
  150.     move.l    (sp)+,a0            // the return address in a0
  151.     movem.l    (sp)+,d0-d2/a1                // which is not restored
  152.     jmp        (a0)
  153. }
  154.  
  155.  
  156.  
  157. pascal void MyDrawMenuBar(void)
  158. {
  159.     long    patchAddress;
  160.  
  161.     EnterCallback();
  162.     saveregisters();
  163.     
  164.     patchAddress = gDrawMenuBarAddress;
  165.  
  166.     /* Install and/or update the menu */
  167.     if (gMenuHandle) {
  168.         OSErr        err = noErr;
  169.         MenuHandle    mh;
  170.         short        i, ch;
  171.         Str255        itemStr;
  172.         
  173.         // delete the old
  174.         for (i=CountMItems(gMenuHandle);i>=1;i--)    { DeleteMenuItem(gMenuHandle, i); }
  175.         
  176.         // append the new!
  177.         err = HMGetHelpMenuHandle(&mh);
  178.         if (!err && mh) {
  179.             for(i=1;i<=CountMItems(mh);i++)    {
  180.                 GetMenuItemText(mh, i, itemStr);
  181.                 AppendMenu(gMenuHandle, "\p ");
  182.                 SetMenuItemText(gMenuHandle, i, itemStr);
  183.                 GetItemCmd(mh, i, &ch);
  184.                 SetItemCmd(gMenuHandle, i, ch);
  185.             }
  186.             
  187.             DeleteMenu((*mh)->menuID);
  188.             // Remember, the memory for mh is still around, just not in the menu.
  189.             InsertMenu(mh, hierMenu);
  190.             gHelpMenu = mh;
  191.         }
  192.                 
  193.         if (!gMenuInstalled) {
  194.             InsertMenu(gMenuHandle, 0);
  195.             gMenuInstalled = true;
  196.         }
  197.     }
  198.         
  199. patchDone:    
  200.     restoreregisters();
  201.     ExitCallback();
  202.  
  203.     callDrawMenuBar(patchAddress);
  204. }
  205.  
  206.  
  207. pascal long MyMenuSelect(Point startPt)
  208. {
  209.     long    patchAddress;
  210.     long    menuResult;
  211.     short    menuID, itemID;
  212.     
  213.     EnterCallback();
  214.     saveregisters();
  215.  
  216.     // Debugger();
  217.     patchAddress = gMenuSelectAddress;    
  218.     menuResult = callMenuSelect(patchAddress, startPt);
  219.     menuID = HiWord(menuResult);    itemID = LoWord(menuResult);
  220.     if (menuID == MyMenuID)    // switch to real help menu!
  221.         menuResult = ((long)kHMHelpMenuID << 16) + itemID;
  222.  
  223.     
  224. msdone:    
  225.     restoreregisters();
  226.     ExitCallback();
  227.     
  228.     return(menuResult);
  229. }
  230.  
  231. pascal long MyMenuKey(short theChar)
  232. {
  233.     long    patchAddress;
  234.     long    menuResult;
  235.     short    menuID, itemID;
  236.     
  237.     EnterCallback();
  238.     saveregisters();
  239.  
  240.     // Debugger();
  241.     patchAddress = gMenuKeyAddress;
  242.     menuResult = callMenuKey(patchAddress, theChar);
  243.     menuID = HiWord(menuResult);    itemID = LoWord(menuResult);
  244.     if (menuID == MyMenuID)    // switch to real help menu!
  245.         menuResult = ((long)kHMHelpMenuID << 16) + itemID;
  246.     
  247. mkdone:
  248.     restoreregisters();
  249.     ExitCallback();
  250.     
  251.     return(menuResult);
  252. }
  253.  
  254. /* This gets called when the user selects one of the items in a system menu */
  255. pascal void MySystemMenu(long menuCode)
  256. {
  257.     long        patchAddress;
  258.     short        menuID = HiWord(menuCode), itemID = LoWord(menuCode);
  259.     
  260.     EnterCallback();
  261.     saveregisters();
  262.  
  263.     // save it off, if we need it!
  264.     patchAddress = gSystemMenuAddress;
  265.  
  266.     // Debugger();
  267.     if (gMenuHandle) {
  268.         if (menuID == MyMenuID) {    /* my menu was selected */
  269.             menuCode = ((long)kHMHelpMenuID << 16) + itemID;
  270.         }
  271.     }
  272.     
  273. smdone:    
  274.     restoreregisters();
  275.     ExitCallback();
  276.  
  277.     callSystemMenu(patchAddress, menuCode);
  278. }
  279.  
  280.  
  281. pascal void MySetMenuItemText(MenuRef theMenu, short item, ConstStr255Param itemString)
  282. {
  283.     OSErr        err = noErr;
  284.     long        patchAddress;
  285.     MenuRef        hMenu;
  286.     
  287.     EnterCallback();
  288.     saveregisters();
  289.  
  290.     // save it off, if we need it!
  291.     patchAddress = gSetItemAddress;
  292.  
  293. //    err = HMGetHelpMenuHandle(&hMenu);
  294.     hMenu = gHelpMenu;
  295.     if (gMenuHandle && hMenu && (theMenu == hMenu) && (item <= CountMItems(gMenuHandle))) {
  296.         // Debugger();
  297.         // SetMenuItemText(gMenuHandle, item, itemString);    // set our item too!
  298.         theMenu = gMenuHandle;
  299.     }
  300.     
  301. smidone:    
  302.     restoreregisters();
  303.     ExitCallback();
  304.  
  305.     callSetMenuItemText(patchAddress, theMenu, item, itemString);
  306. }
  307.  
  308.  
  309. pascal    void MyInsertMenu(MenuRef theMenu, short beforeID)
  310. {
  311.     OSErr        err = noErr;
  312.     long        patchAddress;
  313.     MenuRef        hMenu;
  314.     
  315.     EnterCallback();
  316.     saveregisters();
  317.  
  318.     // save it off, if we need it!
  319.     patchAddress = gInsertMenuAddress;
  320.  
  321.     err = HMGetHelpMenuHandle(&hMenu);
  322.     if (gMenuHandle && hMenu && (theMenu == hMenu)) {
  323.         Debugger();
  324.         beforeID = hierMenu;    // get it out of main menu bar!
  325.     }
  326.     
  327. smidone:    
  328.     restoreregisters();
  329.     ExitCallback();
  330.  
  331.     callInsertMenu(patchAddress, theMenu, beforeID);
  332. }
  333.  
  334.  
  335. /* Determine if a given trap exists */
  336. static Boolean TrapAvailable(long trapNum) 
  337. {
  338.     #define UNIMPL_TRAP         0xA89F
  339.     long     trap1, trap2;
  340.     long     numTraps;
  341.     short         trapType;
  342.     
  343.     /* 
  344.         First, find out how big the trap table is. It will vary on
  345.         different machines. We assume that the trap InitGraf will always
  346.         be implemented. 
  347.     */
  348.     trap1 = (long)NGetTrapAddress(0xAA6E, ToolTrap);
  349.     trap2 = (long)NGetTrapAddress(0xA86E, ToolTrap);
  350.     if (trap1 == trap2)
  351.         numTraps = 0x200;
  352.     else
  353.         numTraps = 0x400;
  354.     
  355.     /* 
  356.         Now, figure out what kind of trap this is, so the client 
  357.         doesn't have to worry about it. 
  358.     */
  359.     if ((trapNum & 0x0800) > 0)
  360.         trapType = ToolTrap;
  361.     else
  362.         trapType = OSTrap;
  363.     
  364.     /* 
  365.         Now, there are no tool box traps after a certain number, 
  366.         so we can rule those out now. 
  367.     */
  368.     if (trapType == ToolTrap) {
  369.         trapNum &= 0x07FF;
  370.         if (trapNum >= numTraps)
  371.             trapNum = UNIMPL_TRAP;
  372.     }
  373.     
  374.     /* Now, compare the trap address to the unimplemented trap address. */
  375.     trap1 = (long)NGetTrapAddress(trapNum, trapType);
  376.     trap2 = (long)NGetTrapAddress(UNIMPL_TRAP, ToolTrap);
  377.     if (trap1 == trap2)
  378.         return(FALSE);
  379.     else
  380.         return(TRUE);
  381. }
  382.  
  383.  
  384. static OSErr GetFileFromRefNum (short fRefNum, short *volID, long *dirID, StringPtr name)
  385. {
  386.     OSErr        err;
  387.     FCBPBPtr    fcbInfoPtr;
  388.  
  389.     fcbInfoPtr = (void*)NewPtrSysClear(sizeof(FCBPBRec));
  390.     if (!(err = MemError())) {
  391.         fcbInfoPtr->ioRefNum = fRefNum;
  392.         fcbInfoPtr->ioNamePtr = name;
  393.         err = PBGetFCBInfoSync(fcbInfoPtr);
  394.         if (!err) {
  395.             *volID = fcbInfoPtr->ioVRefNum;
  396.             if (*volID == 0)    *volID = 0xFFFF;    // means the system disk!
  397.             *dirID = fcbInfoPtr->ioFCBParID;
  398.         }
  399.     }
  400.  
  401.     DisposePtr((Ptr)fcbInfoPtr);
  402.     
  403.     return err;
  404. }
  405.